package service

import (
	"errors"
	"fmt"
	"gorm.io/gorm"
	"seat-service/initialization"
	"seat-service/model"
	"seat-service/model/dto"
	"seat-service/utils"
	"strconv"
	"time"
)

type ClassroomAdminService struct {
}

func (*ClassroomAdminService) DeleteByBuildingIDsWithTransaction(tx *gorm.DB, ids []int) error {
	err := tx.Where("building_id in ?", ids).Delete(&model.Classroom{}).Error
	if err != nil {
		// 删除redis缓存
		idsStr := make([]string, 0, len(ids))
		for _, s := range ids {
			idsStr = append(idsStr, strconv.Itoa(s))
		}
		utils.DeleteMapKey(utils.ClassroomData, idsStr)
		utils.DeleteMapKey(utils.ClassroomId, idsStr)
	}
	return err
}

func (c *ClassroomAdminService) SelectClassroomByCondition(condition dto.GetClassroomCondition) (count int64, classrooms []dto.ClassroomInformations, err error) {
	db := initialization.DB.Model(&model.Classroom{})
	if condition.Location != "" {
		db = db.Where("classrooms.location LIKE ?", "%"+condition.Location+"%")
	}
	if condition.ClassroomStatus != "" {
		db = db.Where("classrooms.classroom_status = ?", condition.ClassroomStatus)
	}
	if condition.ClassroomProperty != "" {
		db = db.Where("classrooms.classroom_property = ?", condition.ClassroomProperty)
	}
	if condition.LockStartTime != "" {
		startTime, err := time.Parse("2006-01-02 15:04", condition.LockStartTime)
		if err != nil {
			return count, nil, err
		}
		db = db.Where("classrooms.lock_start_time <= ?", startTime)
	}
	if condition.LockEndTime != "" {
		endTime, err := time.Parse("2006-01-02 15:04", condition.LockEndTime)
		if err != nil {
			return count, nil, err
		}
		db = db.Where("classrooms.lock_end_time <= ?", endTime)
	}
	if condition.CampusId != 0 {
		db = db.Where("classrooms.campus_id = ?", condition.CampusId)
	}
	if condition.BuildingId != 0 {
		db = db.Joins("LEFT JOIN buildings AS b ON classrooms.building_id = b.id").Where("classrooms.building_id = ?", condition.BuildingId).
			Select("classrooms.id , classrooms.classroom_status , classrooms.location , classrooms.lock_start_time , classrooms.lock_end_time , classrooms.classroom_property , classrooms.seating , classrooms.is_large_classroom, b.name as build_name")
	} else {
		db = db.Joins("LEFT JOIN buildings AS b ON classrooms.building_id = b.id").
			Select("classrooms.id , classrooms.classroom_status , classrooms.location , classrooms.lock_start_time , classrooms.lock_end_time , classrooms.classroom_property , classrooms.seating , classrooms.is_large_classroom, b.name as build_name")
	}
	err = db.Count(&count).Error
	if err != nil {
		return count, nil, err
	}
	// 获取符合条件的总数和分页数据
	err = db.Offset((condition.PageNo - 1) * condition.PageSize).
		Limit(condition.PageSize).
		Scan(&classrooms).
		Error
	return count, classrooms, nil
}

func (c *ClassroomAdminService) SelectClassroomById(classroomId int) (classroom dto.ClassroomInformations, err error) {
	db := initialization.DB.Model(model.Classroom{})
	db = db.Where("classrooms.id = ?", classroomId).Joins("LEFT JOIN buildings as b on b.id = classrooms.building_id").
		Select("classrooms.id , classrooms.classroom_status , classrooms.location , classrooms.lock_start_time , classrooms.lock_end_time , classrooms.classroom_property , classrooms.seating , classrooms.is_large_classroom, b.name as build_name")
	err = db.Scan(&classroom).Error
	return
}

func (c *ClassroomAdminService) UpdateClassroomInformationById(informations dto.ClassroomInformations) (newClassroom dto.ClassroomInformations, err error) {
	// 根据楼栋名称，查询楼栋ID，然后修改教室表中的楼栋ID
	var buildId uint
	err = initialization.DB.Model(&model.Building{}).Select("id").Where("name = ?", informations.BuildName).Scan(&buildId).Error
	if err != nil {
		return
	}
	if buildId == 0 {
		return newClassroom, fmt.Errorf("BuildNotExist")
	}
	// 根据楼栋 查询校区id
	var campusId uint
	err = initialization.DB.Model(&model.Building{}).Select("campus_id").Where("name = ?", informations.BuildName).Scan(&campusId).Error
	updateData := map[string]interface{}{
		"BuildingId":        buildId,
		"Location":          informations.Location,
		"ClassroomStatus":   informations.ClassroomStatus,
		"ClassroomProperty": informations.ClassroomProperty,
		"CampusId":          campusId,
		"Seating":           informations.Seating,
		"IsLargeClassroom":  informations.IsLargeClassroom,
		"LockStartTime":     nil,
		"LockEndTime":       nil,
	}

	if informations.LockStartTime != "" {
		startTime, err := time.Parse("2006-01-02 15:04", informations.LockStartTime)
		if err != nil {
			return newClassroom, err
		}
		updateData["LockStartTime"] = &startTime
	}
	if informations.LockEndTime != "" {
		endTime, err := time.Parse("2006-01-02 15:04", informations.LockEndTime)
		if err != nil {
			return newClassroom, err
		}
		updateData["LockEndTime"] = &endTime
	}

	// 更新教室信息
	err = initialization.DB.Model(&model.Classroom{}).Where("id = ?", informations.ID).Updates(&updateData).Error
	if err != nil {
		return newClassroom, err
	}
	// 更新redis缓存
	classroomData := map[string]string{
		strconv.Itoa(int(informations.ID)): informations.Location,
	}
	classroomId := map[string]string{
		strconv.Itoa(int(informations.ID)): strconv.Itoa(int(buildId)),
	}
	err = utils.CacheRedisData(utils.Classroom, classroomData)
	err = utils.CacheRedisID(utils.Classroom, classroomId)

	// 查询出新的信息
	newClassroom, err = c.SelectClassroomById(informations.ID)
	return newClassroom, err
}

func (c *ClassroomAdminService) AddClassroom(classroom dto.AddClassroom) (err error) {
	// 根据楼栋名称，查询楼栋ID，然后修改教室表中的楼栋ID
	var buildId uint
	err = initialization.DB.Model(&model.Building{}).Select("id").Where("name = ?", classroom.BuildName).Scan(&buildId).Error
	if err != nil {
		return
	}
	if buildId == 0 {
		return fmt.Errorf("BuildNotExist")
	}
	// 根据校区名字 查询校区id
	var campusId uint
	err = initialization.DB.Model(&model.Building{}).Select("campus_id").Where("name = ?", classroom.BuildName).Scan(&campusId).Error
	addData := map[string]interface{}{
		"BuildingId":        buildId,
		"Location":          classroom.Location,
		"ClassroomStatus":   classroom.ClassroomStatus,
		"CampusId":          campusId,
		"Seating":           classroom.Seating,
		"IsLargeClassroom":  classroom.IsLargeClassroom,
		"ClassroomProperty": classroom.ClassroomProperty,
		"LockStartTime":     nil,
		"LockEndTime":       nil,
	}

	if classroom.LockStartTime != "" {
		startTime, err := time.Parse("2006-01-02 15:04", classroom.LockStartTime)
		if err != nil {
			return err
		}
		addData["LockStartTime"] = &startTime
	}
	if classroom.LockEndTime != "" {
		endTime, err := time.Parse("2006-01-02 15:04", classroom.LockEndTime)
		if err != nil {
			return err
		}
		addData["LockEndTime"] = &endTime
	}
	err = initialization.DB.Model(&model.Classroom{}).Create(&addData).Error
	if err != nil {
		return
	}
	var newClassroom model.Classroom
	initialization.DB.Last(&newClassroom) //拿到插入的最后一条记录
	//更新缓存
	classroomData := map[string]string{
		strconv.Itoa(int(newClassroom.ID)): classroom.Location,
	}
	classroomId := map[string]string{
		strconv.Itoa(int(newClassroom.ID)): strconv.Itoa(int(buildId)),
	}
	err = utils.CacheRedisData(utils.Classroom, classroomData)
	err = utils.CacheRedisID(utils.Classroom, classroomId)
	return
}

func (c *ClassroomAdminService) DeleteClassroom(classroom dto.DeleteClassIds) (err error) {
	//删除教室
	classroomIds := classroom.ClassroomIds
	err = initialization.DB.Where("id in (?)", classroomIds).Delete(&model.Classroom{}).Error
	//删除redis中的缓存
	idsStr := make([]string, 0, len(classroomIds))
	for _, value := range classroomIds {
		idsStr = append(idsStr, strconv.Itoa(value))
	}
	err = utils.DeleteMapKey(utils.ClassroomData, idsStr) //删除数据
	err = utils.DeleteMapKey(utils.ClassroomId, idsStr)   //删除中间key中的id
	return
}

func (c *ClassroomAdminService) InsertClassrooms(classrooms []dto.AddClassroom) (errClassrooms []dto.AddClassroom, err error) {
	//遍历数据 更新或者插入数据
	for _, classroom := range classrooms {
		// 根据楼栋名称，查询楼栋ID，然后修改教室表中的楼栋ID
		var buildId uint
		err = initialization.DB.Model(&model.Building{}).Select("id").Where("name = ?", classroom.BuildName).Scan(&buildId).Error
		if err != nil || buildId == 0 {
			errClassrooms = append(errClassrooms, classroom) //错误数据
			continue
		}
		// 根据校区名字 查询校区id
		var campusId uint
		err = initialization.DB.Model(&model.Building{}).Select("campus_id").Where("name = ?", classroom.BuildName).Scan(&campusId).Error
		if err != nil || campusId == 0 {
			errClassrooms = append(errClassrooms, classroom) //错误数据
			continue
		}
		var existClassroom model.Classroom
		var idStr string
		//判断数据是否存在于数据库 中
		// 使用 FirstOrCreate 方法，尝试查询记录，如果不存在则创建
		err = initialization.DB.Where("location = ? and building_id = ?", classroom.Location, buildId).First(&existClassroom).Error
		if err != nil {
			if errors.Is(err, gorm.ErrRecordNotFound) {
				// 记录不存在，创建新记录
				addData := map[string]interface{}{
					"BuildingId":        buildId,
					"Location":          classroom.Location,
					"ClassroomStatus":   classroom.ClassroomStatus,
					"ClassroomProperty": classroom.ClassroomProperty,
					"Seating":           classroom.Seating,
					"IsLargeClassroom":  classroom.IsLargeClassroom,
					"CampusId":          campusId,
					"LockStartTime":     nil,
					"LockEndTime":       nil,
				}
				if classroom.LockStartTime != "" {
					startTime, err := time.Parse("2006-01-02 15:04", classroom.LockStartTime)
					if err != nil {
						errClassrooms = append(errClassrooms, classroom)
						continue
					}
					addData["LockStartTime"] = &startTime
				}
				if classroom.LockEndTime != "" {
					endTime, err := time.Parse("2006-01-02 15:04", classroom.LockEndTime)
					if err != nil {
						errClassrooms = append(errClassrooms, classroom)
						continue
					}
					addData["LockEndTime"] = &endTime
				}
				err = initialization.DB.Model(&model.Classroom{}).Create(&addData).Error
				var newClassroom model.Classroom
				initialization.DB.Last(&newClassroom) //拿到插入的最后一条记录
				idStr = strconv.Itoa(int(newClassroom.ID))
				if err != nil {
					errClassrooms = append(errClassrooms, classroom)
				}
			} else {
				// 处理其他错误
				errClassrooms = append(errClassrooms, classroom)
			}
		} else {
			//数据已经存在 , 更新
			updateData := map[string]interface{}{
				"BuildingId":        buildId,
				"Location":          classroom.Location,
				"ClassroomStatus":   classroom.ClassroomStatus,
				"ClassroomProperty": classroom.ClassroomProperty,
				"CampusId":          campusId,
				"LockStartTime":     nil,
				"LockEndTime":       nil,
			}
			if classroom.LockStartTime != "" {
				startTime, err := time.Parse("2006-01-02 15:04", classroom.LockStartTime)
				if err != nil {
					errClassrooms = append(errClassrooms, classroom)
					continue
				}
				updateData["LockStartTime"] = &startTime
			}
			if classroom.LockEndTime != "" {
				endTime, err := time.Parse("2006-01-02 15:04", classroom.LockEndTime)
				if err != nil {
					errClassrooms = append(errClassrooms, classroom)
					continue
				}
				updateData["LockEndTime"] = &endTime
			}
			// 更新教室信息
			if err = initialization.DB.Model(&existClassroom).Updates(&updateData).Error; err != nil {
				errClassrooms = append(errClassrooms, classroom)
			}
			idStr = strconv.Itoa(int(existClassroom.ID))
		}
		//更新redis中的缓存信息
		classroomData := map[string]string{
			idStr: classroom.Location,
		}
		classroomId := map[string]string{
			idStr: strconv.Itoa(int(buildId)),
		}
		if err := utils.CacheRedisData(utils.Classroom, classroomData); err != nil {
			continue
		}
		if err := utils.CacheRedisID(utils.Classroom, classroomId); err != nil {
			continue
		}
	}
	return
}
func (c *ClassroomAdminService) TimerClassroom(classrooms dto.ClassroomInformations) (err error) {
	var clas model.Classroom
	err = initialization.DB.Model(model.Classroom{}).Where("id=?", classrooms.ID).Scan(clas).Error
	if err != nil {
		return err
	}
	s := classrooms.LockStartTime
	e := classrooms.LockEndTime
	parseS, _ := time.Parse("2006-01-02 15:04:05", s)
	parseE, _ := time.Parse("2006-01-02 15:04:05", e)
	if &parseS != clas.LockStartTime || &parseE != clas.LockEndTime {
		return errors.New("时间已做修改，以后续定时器为准")
	}
	clas.ClassroomStatus = 1
	clas.LockStartTime = nil
	clas.LockEndTime = nil
	err = initialization.DB.Updates(clas).Error
	if err != nil {
		return err
	}
	return nil
}
